var Finch = Finch || {};

var WalletPopup = function(type) {
	this.popup = document.querySelector('.popup-wallet');
	this.content = this.popup.querySelector(
		'.popup-wallet__content--type-' + type
	);
	this.close = this.popup.querySelector('.popup-wallet__close');
	this.buttons = this.popup.querySelectorAll('.popup-wallet__button--later');
	this.html = document.querySelector('html');
	this.body = document.body;

	this.handleClose = this.handleClose.bind(this);

	this.init();
};

WalletPopup.prototype.init = function() {
	this.close.addEventListener('click', this.handleClose);

	this.buttons.forEach(
		function(button) {
			button.addEventListener('click', this.handleClose);
		}.bind(this)
	);
};

WalletPopup.prototype.lockScroll = function() {
	this.body.style.overflow = 'hidden';
};

WalletPopup.prototype.unlockScroll = function() {
	this.body.style.overflow = 'visible';
};

WalletPopup.prototype.show = function() {
	this.lockScroll();
	this.popup.classList.remove('popup-wallet--hidden');
	this.content.classList.remove('popup-wallet__content--hidden');
};

WalletPopup.prototype.hide = function() {
	this.unlockScroll();
	this.popup.classList.add('popup-wallet--hidden');
	this.content.classList.add('popup-wallet__content--hidden');
};

WalletPopup.prototype.handleClose = function() {
	this.hide();
};

Finch.Wallet = {
	subscribers: [],
	balance: {},
	url: null,
	inited: false,
	limits: {
		unidentified: 15000,
		simple: 60000,
	},
	init: function() {
		if (this.inited) {
			return;
		}
		var el = $('[data-balance]');
		if (el.length == 0) {
			return;
		}
		this.inited = true;
		var wallet = el.data('balance');
		this.url = wallet.url.replace('?callback=?', '');
		if (wallet.status == 'ok') {
			this.balance = {
				status: 'ok',
				amount: Math.floor(wallet.sum),
				identSum: Math.floor(wallet.identSum),
				identStatus: wallet.identStatus,
				ident: wallet.ident,
				identLevelText: wallet.identLevelText,
				identStatusText: wallet.identStatusText,
			};
			this.fireEvent();
			this.showPopupIfNeeded(this.balance.ident, this.balance.identSum);
			return;
		}
		if (wallet.status == 'error') {
			this.balance = { status: 'error', amount: 0 };
			this.fireEvent();
			return;
		}
		this.balance = { status: 'pending', amount: 0 };
		this.load();
	},
	load: function() {
		new AsyncHandler(
			1000,
			this.url,
			{},
			'GET',
			$.proxy(function(data) {
				this.onBalance(data);
			}, this),
			$.proxy(function(data) {
				this.onError();
			}, this)
		).start();
	},
	onBalance: function(data) {
		this.balance = {
			status: data.status.toLowerCase(),
			amount: Math.floor(data.sum),
			identSum: Math.floor(data.identSum),
			ident: data.ident,
			identLevelText: data.identLevelText,
			identStatusText: data.identStatusText,
		};
		this.fireEvent();
	},
	onError: function() {
		this.balance = { status: 'error' };
		this.fireEvent();
	},
	showPopupIfNeeded: function(ident, identSum) {
		/* considering positive identSum means limit overrun */
		if (
			location.pathname === '/cabinet/wallet' &&
			ident === 'unidentified' &&
			identSum > 0
		) {
			var popup = new WalletPopup(ident);
			popup.show();
		}
	},
	isDocumentOutdated: function() {
		return (
			this.balance.identStatusText === 'Документ более недействителен' &&
			(this.balance.ident === 'simple' || this.balance.ident === 'full')
		);
	},
	/* called manually */
	showDocumentPopup: function() {
		var popup = new WalletPopup('documentOutdated');
		popup.show();
	},
	getNewBalance: function() {
		var identSum = this.balance.identSum;
		var ident = this.balance.ident;

		var balance = $.ajax({
			url: '/service/private/w1/balance',
			dataType: 'json',
		}).done(
			function(data) {
				if (data.status === 'ok') {
					this.balance.status = 'ok';
					this.balance.amount = Math.floor(data.sum);
					this.balance.identSum = Math.floor(data.identSum);
					this.balance.identStatus = data.identStatus;
					this.balance.ident = data.ident;
					this.balance.identLevelText = data.identLevelText;
					this.balance.identStatusText = data.identStatusText;

					this.showPopupIfNeeded(
						this.balance.ident,
						this.balance.identSum
					);
				}
			}.bind(this)
		);

		return Object.assign(
			{
				amount: this.balance.amount,
				subAmount: this.balance.identSum,
			},
			identSum !== 'undefined' ? { identSum: identSum } : {},
			ident !== 'undefined' ? { ident: ident } : {}
		);

		return 0;
	},
	isOk: function() {
		return this.balance.status == 'ok';
	},
	isPending: function() {
		return this.balance.status == 'pending';
	},
	isError: function() {
		return this.balance.status == 'error';
	},
	getFormattedBalance: function() {
		if (!this.isOk()) {
			return '0';
		}
		var b = this.getNewBalance().amount;
		if (b >= 1000000) {
			var right = Math.floor(b % 1000);
			var middle = Math.floor((b % 1000000) / 1000);
			var left = Math.floor(b / 1000000);
			if (right < 10) {
				right = '00' + right;
			} else if (right < 100) {
				right = '0' + right;
			}
			if (middle < 10) {
				middle = '00' + middle;
			} else if (middle < 100) {
				middle = '0' + middle;
			}
			b =
				'<span class="formated-balance">' +
				left +
				'</span><span class="formated-balance">' +
				middle +
				'</span><span class="formated-balance">' +
				right +
				'</span>';
		} else if (b >= 10000) {
			var right = Math.floor(b % 1000);
			if (right < 10) {
				right = '00' + right;
			} else if (right < 100) {
				right = '0' + right;
			}
			b =
				'<span class="formated-balance">' +
				Math.floor(b / 1000) +
				'</span><span class="formated-balance">' +
				right +
				'</span>';
		}
		return b;
	},
	subscribe: function(listener) {
		this.subscribers.push(listener);
		if (!this.isPending()) {
			this.fireEvent(listener);
		}
	},
	fireEvent: function(listener) {
		var listeners = this.subscribers;
		if (listener) {
			listeners = [listener];
		}
		if (this.isOk()) {
			for (var i = 0; i < listeners.length; i++) {
				listeners[i](
					'ok',
					this.getNewBalance(),
					this.getFormattedBalance()
				);
			}
		} else {
			for (var i = 0; i < listeners.length; i++) {
				listeners[i]('error', 0, '0');
			}
		}
	},
	refresh: function() {
		this.balance = { status: 'pending' };
		this.load();
	},
};

Finch.Bonus = {
	subscribers: [],
	balance: { status: 'pending' },
	bonusArray: ['бонус', 'бонусов', 'бонуса'],
	url: null,
	inited: false,
	init: function() {
		if (this.inited) {
			return;
		}
		var el = $('[data-bonus-balance]');
		if (el.length == 0) {
			return;
		}
		this.inited = true;
		var bonus = el.data('bonusBalance');
		this.url = bonus.url.replace('?callback=?', '');
		if (bonus.status == 'ok') {
			this.balance = { status: 'ok', amount: Math.floor(bonus.sum) };
			this.fireEvent();
			return;
		}
		if (bonus.status == 'error') {
			this.balance = { status: 'error', amount: 0 };
			this.fireEvent();
			return;
		}
		this.load();
	},
	load: function() {
		new AsyncHandler(
			1000,
			this.url,
			{},
			'jsonp',
			$.proxy(function(data) {
				this.onBalance(data);
			}, this),
			$.proxy(function(data) {
				this.onError();
			}, this)
		).start();
	},
	onBalance: function(data) {
		this.balance = {
			status: data.status.toLowerCase(),
			amount: Math.floor(data.sum),
		};
		this.fireEvent();
	},
	onError: function() {
		this.balance = { status: 'error' };
		this.fireEvent();
	},
	getNewBalance: function() {
		if (this.balance.status == 'ok') {
			return this.balance.amount;
		}
		return 0;
	},
	isOk: function() {
		return this.balance.status == 'ok';
	},
	isPending: function() {
		return this.balance.status == 'pending';
	},
	isError: function() {
		return this.balance.status == 'error';
	},
	getFormattedBalance: function() {
		if (!this.isOk()) {
			return '0';
		}
		var b = this.getNewBalance();
		if (b >= 1000000) {
			var right = Math.floor(b % 1000);
			var middle = Math.floor((b % 1000000) / 1000);
			var left = Math.floor(b / 1000000);
			if (right < 10) {
				right = '00' + right;
			} else if (right < 100) {
				right = '0' + right;
			}
			if (middle < 10) {
				middle = '00' + middle;
			} else if (middle < 100) {
				middle = '0' + middle;
			}
			b =
				'<span class="formated-balance">' +
				left +
				'</span><span class="formated-balance">' +
				middle +
				'</span><span class="formated-balance">' +
				right +
				'</span>';
		} else if (b >= 10000) {
			var right = Math.floor(b % 1000);
			if (right < 10) {
				right = '00' + right;
			} else if (right < 100) {
				right = '0' + right;
			}
			b =
				'<span class="formated-balance">' +
				Math.floor(b / 1000) +
				'</span><span class="formated-balance">' +
				right +
				'</span>';
		}
		return b;
	},
	subscribe: function(listener) {
		this.subscribers.push(listener);
		if (!this.isPending()) {
			this.fireEvent(listener);
		}
	},
	fireEvent: function(listener) {
		var listeners = this.subscribers;
		if (listener) {
			listeners = [listener];
		}
		if (this.isOk()) {
			for (var i = 0; i < listeners.length; i++) {
				listeners[i](
					'ok',
					this.getNewBalance(),
					this.getFormattedBalance()
				);
			}
		} else {
			for (var i = 0; i < listeners.length; i++) {
				listeners[i]('error', 0, '0');
			}
		}
	},
	refresh: function() {
		this.balance = { status: 'pending' };
		this.load();
	},
};

Finch.Identification = {
	cookie: 'identificationDelayed',
	confirmCallbackSet: false,
	getCookie: function() {
		var matches = document.cookie.match(
			new RegExp('(?:^|; )' + Finch.Identification.cookie + '=([^;]*)')
		);
		return matches ? decodeURIComponent(matches[1]) : null;
	},
	init: function() {
		var identData = $('#identification_required');
		if (window.currentUser && identData.length > 0) {
			var status = identData.data('identificationstatus');
			if (status == 'expired' || status == 'document_invalid') {
				var c = Finch.Identification.getCookie();
				if (!c) {
					Finch.Identification.popup(status);
				}
			}
		}
	},
	popup: function(status) {
		var p = Popup.show('ident', function(popup) {
			popup.find('.popup_ident .ident_status').hide();
			popup.find('.' + status).show();
		});
		if (status == 'expired') {
			if (!this.confirmCallbackSet) {
				this.confirmCallbackSet = true;
				$('.confirm', p.element).click(function() {
					var ahm = new AsyncHandlerMobile(
						$('#identification_required').data(
							'identificationConfirmUrl'
						),
						'POST',
						{},
						1000,
						5,
						Finch.Identification.closePopup,
						Finch.Identification.closePopup,
						Finch.Identification.closePopup
					);
					return false;
				});
			}
		}
		if (status == 'expired' || status == 'document_invalid') {
			p.closeButton
				.unbind('click')
				.click(Finch.Identification.closePopup);
		} else {
			p.closeButton.unbind('click').click(Popup.close);
		}
	},
	closePopup: function() {
		Finch.Identification.setCookie();
		Popup.close();
	},
	setCookie: function() {
		document.cookie = Finch.Identification.cookie + '=123;';
	},
};

function AsyncHandler(
	interval,
	url,
	data,
	method,
	successHandler,
	errorHandler,
	fatalHandler,
	json,
	pendingHandler
) {
	var that = this;
	this.counter = 0;
	this.isInProgress = false;
	this.successHandler = successHandler;
	this.errorHandler = errorHandler;
	this.fatalHandler = fatalHandler;
	this.ignoreRedirects = data.ignoreRedirects;
	this.intervalHandler = function() {
		if (that.isInProgress) {
			return;
		}
		if (that.counter > 60) {
			clearInterval(that.handler);
			if (that.fatalHandler) that.fatalHandler();
			that.counter = 0;
			return;
		}
		that.counter++;
		that.isInProgress = true;
		jQuery.ajax({
			url: url,
			type: method == 'jsonp' ? 'GET' : method,
			dataType: method == 'jsonp' ? 'jsonp' : 'json',
			contentType:
				method === 'POST' && !json
					? 'application/x-www-form-urlencoded'
					: 'application/json',
			data: data,
			cache: false,
			success: function(data) {
				that.isInProgress = false;
				if (data.status == 'pending') {
					if (pendingHandler) {
						pendingHandler(data);
					}
					return;
				}
				clearInterval(that.handler);
				if (data.status == 'not.auth') {
					document.location.href =
						'/login?targetUrl=' +
						encodeURI(data.url ? data.url : document.location.href);
					return;
				}
				if (data.url && !that.ignoreRedirects) {
					document.location.href = data.url;
					return;
				}
				if (data.status == 'error') {
					if (that.errorHandler) that.errorHandler(data);
				} else {
					if (that.successHandler) that.successHandler(data);
				}
			},
			error: function() {
				that.isInProgress = false;
				clearInterval(that.handler);
				if (that.fatalHandler) that.fatalHandler();
			},
		});
	};

	this.start = function() {
		this.intervalHandler();
		this.handler = setInterval(this.intervalHandler, interval);
	};
}

var AsyncHandlerMobile = function(
	url,
	method,
	body,
	attemptDelay,
	maxAttempts,
	onSuccess,
	onFail,
	onAttemptsEnded,
	data
) {
	this.request = {
		url: url,
		method: method,
		body: body,
	};
	this.attemptDelay = attemptDelay;
	this.maxAttempts = maxAttempts;
	this.data = data || {};
	this.ignoreRedirects = this.data.ignoreRedirects;
	this.handlers = {
		success: onSuccess,
		fail: onFail,
		attemptsEnded: onAttemptsEnded,
	};

	this.clearInterval = this.clearInterval.bind(this);
	this.handleRequest = this.handleRequest.bind(this);
	this.handleSuccess = this.handleSuccess.bind(this);
	this.handleFail = this.handleFail.bind(this);

	this.isFetching = false;
	this.intervalId = null;
	this.currentAttempt = 0;

	this.createInterval(this.handleRequest);
};

AsyncHandlerMobile.serverStatuses = {
	pending: 'pending',
	notAuth: 'not.auth',
	fail: 'error',
};

AsyncHandlerMobile.prototype.createInterval = function(handler) {
	this.intervalId = setInterval(function() {
		handler();
	}, this.attemptDelay);
};

AsyncHandlerMobile.prototype.clearInterval = function() {
	clearInterval(this.intervalId);
	this.intervalId = null;
};

AsyncHandlerMobile.prototype.handleAttemptsLimit = function(cb) {
	if (this.currentAttempt === this.maxAttempts) {
		cb();
		this.isFetching = false;
		this.currentAttempt = 0;
		this.handlers.attemptsEnded();
	}
};

AsyncHandlerMobile.prototype.handleRequest = function() {
	this.isFetching = true;
	this.currentAttempt += 1;

	jQuery.ajax({
		url: this.request.url,
		type: this.request.method === 'jsonp' ? 'GET' : this.request.method,
		dataType: this.request.method === 'jsonp' ? 'jsonp' : 'json',
		data: this.request.body,
		cache: false,
		success: function(response) {
			this.handleSuccess(response);
			this.handleAttemptsLimit(this.clearInterval);
		}.bind(this),
		error: function(error) {
			this.handleFail(error);
			this.clearInterval();
		}.bind(this),
	});
};

AsyncHandlerMobile.prototype.handleSuccess = function(response) {
	var status = response.status;

	if (status !== this.constructor.serverStatuses.pending) {
		this.clearInterval();

		if (status === this.constructor.serverStatuses.notAuth) {
			window.location.replace(
				'/login?targetUrl=' +
					encodeURI(
						response.url ? response.url : window.location.href
					)
			);
			return;
		}
		if (response.url && !this.ignoreRedirects) {
			window.location.href = response.url;
			return;
		}

		if (status === this.constructor.serverStatuses.fail) {
			this.handleFail(response);
		} else {
			this.handlers.success(response);
		}
	}
};

AsyncHandlerMobile.prototype.handleFail = function(error) {
	this.isFetching = false;
	this.currentAttempt = 0;

	if (this.handlers.fail) {
		this.handlers.fail(error);
	}
};

function PopupController(content, title, hasCloseButton, closeButtonText) {
	this.title = title || '';
	this.hasCloseButton = hasCloseButton || false;
	this.buttonText = closeButtonText || 'Закрыть';
	this.content = content || '';

	this.popupContainer = document.createElement('div');
	this.popupContainer.classList.add('mobile-popup','mobile-popup_hidden');
	this.popupContainer.innerHTML = '<div class="mobile-popup__overlay"></div><div class="mobile-popup__wrapper"><div class="mobile-popup__close"><div class="ico ico_close"></div></div><div class="mobile-popup__container">' + (this.title ? '<h4 class="mobile-popup__title">' + this.title + '</h4>' : '') + '<div class="mobile-popup__content">' + this.content + '</div><div class="mobile-popup__controls">' + (this.hasButton ? '<button type="button" class="mobile-popup__button mobile-popup__button_close">' + this.buttonText + '</button>' : '') + '</div></div></div>';
	document.querySelector('body').appendChild(this.popupContainer);

	this.handleOpen = this.handleOpen.bind(this);
	this.handleClose = this.handleClose.bind(this);
	this.init = this.init.bind(this);

	this.init();
}

PopupController.prototype.handleOpen = function() {
	this.popupContainer.classList.remove('mobile-popup_hidden');
}

PopupController.prototype.handleClose = function() {
	this.popupContainer.classList.add('mobile-popup_hidden');
}

PopupController.prototype.init = function() {
	var closePopupSelectors = [
		'.mobile-popup__close',
		'.mobile-popup__overlay'
	].concat(this.hasCloseButton ? ['.mobile-popup__button_close'] : []);

	closePopupSelectors.forEach(function(selector) {
		document.querySelector(selector).addEventListener('click', this.handleClose);
	})
}

function formatNumber(number) {
	return number
		.toString(10)
		.split('')
		.reduce(function(acc, value, index, array) {
			var radixIndex = array.length - index;
			var stringValue =
				index > 0 && radixIndex % 3 === 0 ? ' ' + value : value;
			return acc + stringValue;
		}, '');
}

function AutopaymentPopup() {
	this.MIN_SUM = 0;
	this.MAX_SUM = 14999;
	this.sum = $('.cabinet-ticket-autopayment').data('sum');
	this.popup = document.querySelector('.popup-autopayment');
	if (!this.popup) return false;
	this.close = this.popup.querySelector('.popup-autopayment__close');
	this.content = this.popup.querySelector('.popup-autopayment__content');
	this.sumInput = this.popup.querySelector(
		'.popup-autopayment__form-input--sum'
	);
	this.body = document.body;
	this.currentType = 'init';
	this.loading = false;
	this.buttons = this.popup.querySelectorAll('.popup-autopayment__button');
	this.form = this.popup.querySelector('.popup-autopayment__form');
	this.finishButton = this.buttons[1];
	this.autoPaymentButton = document.querySelector(
		'.cabinet-ticket-autopayment__autopay'
	);
	this.settingsButton = document.querySelector(
		'.cabinet-ticket-autopayment__settings-button'
	);
	this.htmlSum = $('.popup-autopayment__sum');

	this.handleChangeSum = this.handleChangeSum.bind(this);
	this.setAutopayment = this.setAutopayment.bind(this);
	this.handleSubmit = this.handleSubmit.bind(this);
	this.handleFinish = this.handleFinish.bind(this);
	this.togglePopup = this.togglePopup.bind(this);
	this.handleToggleClick = this.handleToggleClick.bind(this);

	this.init();
}

AutopaymentPopup.prototype.init = function() {
	this.sumInput.addEventListener('input', this.handleChangeSum);
	this.form.addEventListener('submit', this.handleSubmit);
	this.finishButton.addEventListener('click', this.handleFinish);
	this.autoPaymentButton.addEventListener('click', this.handleToggleClick);
	this.close.addEventListener('click', this.togglePopup);
	this.settingsButton.addEventListener('click', this.togglePopup);
};

AutopaymentPopup.prototype.handleChangeSum = function(ev) {
	var value = ev.target.value;

	if (value > this.MAX_SUM) {
		ev.target.value = this.MAX_SUM;
	} else if (this.sum < this.MIN_SUM) {
		ev.target.value = this.MIN_SUM;
	} else {
		ev.target.value = value;
	}
};

AutopaymentPopup.prototype.toggleScroll = function() {
	var isLock = this.body.style.overflow === 'hidden';

	if (isLock) {
		this.body.style.overflow = 'visible';
	}

	this.body.style.overflow = 'hidden';
};

AutopaymentPopup.prototype.toggleButtonsState = function() {
	[].forEach.call(this.buttons, function(button) {
		button.classList.toggle('popup-autopayment__button--disabled');
	});
};

AutopaymentPopup.prototype.togglePopup = function() {
	this.popup.classList.toggle('popup-autopayment--hidden');

	this.changeType('init');
};

AutopaymentPopup.prototype.handleToggleClick = function() {
	if (this.sum > 0) {
		this.setAutopayment(0);
	} else {
		this.togglePopup();
	}
};

AutopaymentPopup.prototype.handleSubmit = function(ev) {
	ev.preventDefault();
	this.setAutopayment(this.sumInput.value);
};

AutopaymentPopup.prototype.handleFinish = function(ev) {
	ev.preventDefault();

	this.changeType('success');
	this.togglePopup();
};

AutopaymentPopup.prototype.changeType = function(type) {
	var contentClass = 'popup-autopayment__content--';
	var hiddenContentClass = 'popup-autopayment__content--hidden';

	this.popup
		.querySelector('.' + contentClass + this.currentType)
		.classList.add(hiddenContentClass);
	this.popup
		.querySelector('.' + contentClass + type)
		.classList.remove(hiddenContentClass);

	this.currentType = type;
};

AutopaymentPopup.prototype.setAutopayment = function(value) {
	this.toggleButtonsState();
	var isOff = value == 0;
	var self = this;
	var params = isOff
		? '&is_withdrawal=off'
		: '&withdrawal_sum=' + value + '&is_withdrawal=on';
	fetch('/service/private/autopayment', {
		method: 'POST',
		headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
		body: 'withdrawal_type=wallet' + params,
	})
		.then(
			function(response) {
				if (
					response.status !== 200 ||
					response.json().status === 'error'
				) {
					alert(
						'Что-то пошло не так, попробуйте обновить страницу или повторите попытку позднее'
					);
				}
				self.sum = value;
				self.htmlSum.text(self.sum);
				$('.cabinet-ticket-autopayment__label--on').toggleClass(
					'cabinet-ticket-autopayment__label--hidden',
					isOff
				);
				$('.cabinet-ticket-autopayment__label--off').toggleClass(
					'cabinet-ticket-autopayment__label--hidden',
					!isOff
				);

				this.toggleButtonsState();
				if (!isOff) {
					this.changeType('success');
				}
				$('.cabinet-ticket-autopayment__autopay').toggleClass(
					'cabinet-ticket-payment__switch-outer--off',
					isOff
				);
			}.bind(this)
		)
		.catch(
			function(err) {
				console.log(err);
				alert(
					'Что-то пошло не так, попробуйте обновить страницу или повторите попытку позднее'
				);

				this.toggleButtonsState();
			}.bind(this)
		);
};

new AutopaymentPopup();
